﻿#pragma once
#include "yzrutil.h"
#include "io/InputStream.h"
#include "collection/ArrayList.hpp"
#include "io/DataInputStream.h"
#include "array/Arrays.h"
#include "lang/StringFormat.hpp"
#include "lang/String.h"

namespace yzrilyzr_util{
	EBCLASS(MIDIFile){
	public:
	enum EventType{
		FF, Sysex, Note, ChannelPitchBend, ChannelPressure, ProgramChange, ChannelControl
	};
	EBCLASS(CC){
	public:
	static constexpr int32_t BANK=0;//用来切换音色选择库，每个MIDI通道可以访问16384个音色；
	static constexpr int32_t MODULATION=1;//通常用来控制颤音效果(vibrato effect)，包括音高响度亮度等等；
	static constexpr int32_t BREATH=2;//呼吸控制器：通常关联aftertouch信息，最初旨在和呼吸控制器一起使用，例如用力吹气会产生更高的MIDI控制值，也可以用来当作Modulation使用；
	static constexpr int32_t UNDEFINED_3=3;
	static constexpr int32_t FOOT=4;//Foot控制器：通常关联aftertouch信息，可以根据踏板的踩踏方式发送连续的值信息；
	static constexpr int32_t PORTAMENTO_TIME=5;//Portamento(滑音)时间：在两个连续演奏的音符之间控制滑音速率；
	static constexpr int32_t DATA_ENTRY_MSB=6;//Data Entry Most Significant Bit(MSB)：控制NRPN或RPN的参数值；
	static constexpr int32_t DATA_ENTRY_LSB=38;//Data Entry Least Significant Bit(LSB)：控制NRPN或RPN的参数值；
	static constexpr int32_t VOLUME=7;//控制通道的音量；
	static constexpr int32_t BALANCE=8;//控制左右平衡，产生立体声声音，0是绝对左边，64是中间，127是绝对右边；
	static constexpr int32_t UNDEFINED_9=9;
	static constexpr int32_t PAN=10;//控制左右平衡，产生单声道声音，0是绝对左边，64是中间，127是绝对右边；
	static constexpr int32_t EXPRESSION=11;//表情：用来控制表情；
	static constexpr int32_t EFFECT_12=12;//效果控制器1：通常用来控制合成器或工作站的某个效果器参数；；
	static constexpr int32_t EFFECT_13=13;//效果控制器2：通常用来控制合成器或工作站的某个效果器参数；；
	static constexpr int32_t UNDEFINED_14=14;
	static constexpr int32_t UNDEFINED_15=15;
	static constexpr int32_t PERFORMANCE_MODULATION_16=16;
	static constexpr int32_t PERFORMANCE_MODULATION_17=17;
	static constexpr int32_t PERFORMANCE_MODULATION_18=18;
	static constexpr int32_t PERFORMANCE_MODULATION_19=19;
	//			32 － 63 Controller 0-31 Least Significant Bit (LSB)：对应0到31号控制器，对参数进行微调；
	static constexpr int32_t SUSTAIN_SWITCH=64;//Damper(制音)踏板 ／ 延音踏板控制：On/Off switch that controls sustain. (See also Sostenuto CC 66) 0 to 63 = Off, 64 to 127 = On；
	static constexpr int32_t PORTAMENTO_SWITCH=65;//Portamento(滑音)切换开关：0 to 63 = Off, 64 to 127 = On；
	static constexpr int32_t SOSTENUTO_SWITCH=66;//sostenuto(持续音)切换开关：On/Off switch – Like the Sustain controller (CC 64), However it only holds notes that were “On” when the pedal was pressed. People use it to “hold” chords” and play melodies over the held chord；
	static constexpr int32_t SOFT_PEDAL_SWITCH=67;//弱音踏板(Soft Pedal)：On/Off switch - Lowers the volume of notes played. 0 to 63 = O, 64 to 127 = On；
	static constexpr int32_t LEGATO_EFFECT_SWITCH=68;//连奏脚踏开关：On/Off switch - Turns Legato effect between 2 subsequent notes On or Off. 0 to 63 = O, 64 to 127 = On；
	static constexpr int32_t SUSTAIN2=69;//保持音2：另一种制造持续音的方法(查看MIDI CC 64或MIDI CC 66)；
	//
	static constexpr int32_t SOUND_VARIATION=70;//通常控制声音的产生方式，默认是Sound Variation；
	static constexpr int32_t FILTER_RESONANCE=71;//允许对受控滤波器进行重塑，默认是resonance(共振)，也可以是timbre(音色)或harmonics(谐波)；
	static constexpr int32_t RELEASE_TIME=72;//对受控放大器的释放时间进行控制，默认是Release Time；
	static constexpr int32_t ATTACK_TIME=73;//控制声音的“Attack”；
	static constexpr int32_t FILTER_CUTOFF=74;//控制受控滤波器的滤波频率；
	static constexpr int32_t DECAY_TIME=75;//通用声音控制；
	static constexpr int32_t VIBRATO_RATE=76;//通用声音控制；
	static constexpr int32_t VIBRATO_DEPTH=77;//通用声音控制；
	static constexpr int32_t VIBRATO_DELAY=78;//通用声音控制；
	static constexpr int32_t SOUND_CONTROLLER_79=79;//通用声音控制；
	static constexpr int32_t SWITCH_80=80;//80 一般用途的MIDI CC控制器：开关切换 0到63为Off，64到127为On；
	static constexpr int32_t SWITCH_81=81;//81 一般用途的MIDI CC控制器：开关切换 0到63为Off，64到127为On；
	static constexpr int32_t SWITCH_82=82;//82 一般用途的MIDI CC控制器：开关切换 0到63为Off，64到127为On；
	static constexpr int32_t SWITCH_83=83;//83 一般用途的MIDI CC控制器：开关切换 0到63为Off，64到127为On；
	//
	static constexpr int32_t EFFECT_REVERB=91;//效果1深度：通常控制reverb发送量；
	static constexpr int32_t EFFECT_TREMOLO=92;//效果2深度：通常控制tremolo(颤音)量；
	static constexpr int32_t EFFECT_CHORUS=93;//效果3深度：通常控制chorus(合唱)量；
	static constexpr int32_t EFFECT_DETUNE=94;//效果4深度：通常控制detune(失谐)量；
	static constexpr int32_t EFFECT_PHASER=95;//效果5深度：通常控制phaser(移相)量；
	//
	static constexpr int32_t DATA_BOUND_INCREMENT=96;//数据增益：通常用来增加RPN和NRPN信息的数据；
	static constexpr int32_t DATA_BOUND_DECREMENT=97;//数据衰减：通常用来衰减RPN和NRPN信息的数据；
	//
	static constexpr int32_t NRPN_LSB=98;//未注册的LSB(NRPN)参数值：对6、38、96和97号控制器来说，选择的是NRPN参数；
	static constexpr int32_t NRPN_MSB=99;//未注册的MSB(NRPN)参数值：对6、38、96和97号控制器来说，选择的是NRPN参数；
	static constexpr int32_t RPN_LSB=100;//注册的LSB(RPN)参数值：对6、38、96和97号控制器来说，选择的是RPN参数；
	static constexpr int32_t RPN_MSB=101;//注册的MSB(RPN)参数值：对6、38、96和97号控制器来说，选择的是RPN参数；
	//
	static constexpr int32_t RESET_MUTE_ALL_NOTES=120;//关闭所有声音：静音所有音符，无论是否存在释放时间或是否处于sustain；
	static constexpr int32_t RESET_ALL_CONTROLLERS=121;//重置所有控制器：将所有控制器重置为默认值；
	static constexpr int32_t CLOSE_KEYBOARD=122;//本地键盘开关：关闭MIDI键盘或工作站的内部连接等等；
	static constexpr int32_t ALL_NOTES_OFF=123;//关闭所有音符：静音所有音符，但释放时间会保留，并且音符的延音不会关闭，直到延音踏板没有被按下；
	static constexpr int32_t OMNI_OFF=124;//Omni模式关闭：设置为“Omni Off”模式；
	static constexpr int32_t OMNI_ON=125;//Omni模式开启：设置为“Omni On”模式；
	static constexpr int32_t MONO_MODE=126;//Mono模式：将设备设置为单音模式；
	static constexpr int32_t POLY_MODE=127;//Poly模式：将设备设置为复音模式；
	};
	EBCLASS(Instruments){
		//钢琴类
	public:
	static constexpr int32_t PIANO_ACOUSTIC_GRAND_PIANO=0;//大钢琴（声学钢琴）
	static constexpr int32_t PIANO_BRIGHT_ACOUSTIC_PIANO=1;//明亮的钢琴
	static constexpr int32_t PIANO_ELECTRIC_GRAND_PIANO=2;//电钢琴
	static constexpr int32_t PIANO_HONKY_TONK_PIANO=3;//_酒吧钢琴
	static constexpr int32_t PIANO_ELECTRIC_PIANO_1=4;//柔和的电钢琴
	static constexpr int32_t PIANO_ELECTRIC_PIANO_2=5;//加合唱效果的电钢琴
	static constexpr int32_t PIANO_HARPSICHORD=6;//羽管键琴（拨弦古钢琴）
	static constexpr int32_t PIANO_CLAVICHORD=7;//科拉维科特琴（击弦古钢琴）
	//色彩打击乐器类
	static constexpr int32_t CHROMATIC_PERCUSSION_CELESTA=8;//钢片琴
	static constexpr int32_t CHROMATIC_PERCUSSION_GLOCKENSPIEL=9;//钟琴
	static constexpr int32_t CHROMATIC_PERCUSSION_MUSIC_BOX=10;//八音盒
	static constexpr int32_t CHROMATIC_PERCUSSION_VIBRAPHONE=11;//颤音琴
	static constexpr int32_t CHROMATIC_PERCUSSION_MARIMBA=12;//马林巴琴
	static constexpr int32_t CHROMATIC_PERCUSSION_XYLOPHONE=13;//木琴
	static constexpr int32_t CHROMATIC_PERCUSSION_TUBULAR_BELLS=14;//管钟
	static constexpr int32_t CHROMATIC_PERCUSSION_DULCIMER=15;//大扬琴
	//风琴类
	static constexpr int32_t ORGAN_HAMMOND_ORGAN=16;//击杆风琴
	static constexpr int32_t ORGAN_PERCUSSIVE_ORGAN=17;//打击式风琴
	static constexpr int32_t ORGAN_ROCK_ORGAN=18;//摇滚风琴
	static constexpr int32_t ORGAN_CHURCH_ORGAN=19;//教堂风琴
	static constexpr int32_t ORGAN_REED_ORGAN=20;//簧管风琴
	static constexpr int32_t ORGAN_ACCORDIAN=21;//手风琴
	static constexpr int32_t ORGAN_HARMONICA=22;//口琴
	static constexpr int32_t ORGAN_TANGO_ACCORDIAN=23;//探戈手风琴
	//		吉他类
	static constexpr int32_t GUITAR_ACOUSTIC_GUITAR_NYLON=24;//尼龙弦吉他
	static constexpr int32_t GUITAR_ACOUSTIC_GUITAR_STEEL=25;//钢弦吉他
	static constexpr int32_t GUITAR_ELECTRIC_GUITAR_JAZZ=26;//爵士电吉他
	static constexpr int32_t GUITAR_ELECTRIC_GUITAR_CLEAN=27;//清音电吉他
	static constexpr int32_t GUITAR_ELECTRIC_GUITAR_MUTED=28;//闷音电吉他
	static constexpr int32_t GUITAR_OVERDRIVEN_GUITAR=29;//加驱动效果的电吉他
	static constexpr int32_t GUITAR_DISTORTION_GUITAR=30;//加失真效果的电吉他
	static constexpr int32_t GUITAR_GUITAR_HARMONICS=31;//吉他和音
	//		贝司类
	static constexpr int32_t BASS_ACOUSTIC_BASS=32;//大贝司（声学贝司）
	static constexpr int32_t BASS_ELECTRIC_BASS_FINGER=33;//电贝司（指弹）
	static constexpr int32_t BASS_ELECTRIC_BASS_PICK=34;//电贝司（拨片）
	static constexpr int32_t BASS_FRETLESS_BASS=35;//无品贝司
	static constexpr int32_t BASS_SLAP_BASS_1=36;//掌击贝司_1
	static constexpr int32_t BASS_SLAP_BASS_2=37;//掌击贝司_2
	static constexpr int32_t BASS_SYNTH_BASS_1=38;//电子合成贝司_1
	static constexpr int32_t BASS_SYNTH_BASS_2=39;//电子合成贝司_2
	//弦乐类
	static constexpr int32_t SOLO_STRING_VIOLIN=40;//小提琴
	static constexpr int32_t SOLO_STRING_VIOLA=41;//中提琴
	static constexpr int32_t SOLO_STRING_CELLO=42;//大提琴
	static constexpr int32_t SOLO_STRING_CONTRABASS=43;//低音大提琴
	static constexpr int32_t SOLO_STRING_TREMOLO_STRINGS=44;//弦乐群颤音
	static constexpr int32_t SOLO_STRING_PIZZICATO_STRINGS=45;//弦乐群拨弦
	static constexpr int32_t SOLO_STRING_ORCHESTRAL_HARP=46;//竖琴
	static constexpr int32_t SOLO_STRING_TIMPANI=47;//定音鼓
	//合奏/合唱类
	static constexpr int32_t ENSEMBLE_STRING_ENSEMBLE_1=48;//弦乐合奏1
	static constexpr int32_t ENSEMBLE_STRING_ENSEMBLE_2=49;//弦乐合奏2
	static constexpr int32_t ENSEMBLE_SYNTH_STRINGS_1=50;//合成弦乐合奏1
	static constexpr int32_t ENSEMBLE_SYNTH_STRINGS_2=51;//合成弦乐合奏2
	static constexpr int32_t ENSEMBLE_CHOIR_AAHS=52;//人声合唱“啊”
	static constexpr int32_t ENSEMBLE_VOICE_OOHS=53;//人声“嘟”
	static constexpr int32_t ENSEMBLE_SYNTH_VOICE=54;//合成人声
	static constexpr int32_t ENSEMBLE_ORCHESTRA_HIT=55;//管弦乐敲击齐奏
	//		铜管类
	static constexpr int32_t BRASS_TRUMPET=56;//小号
	static constexpr int32_t BRASS_TROMBONE=57;//长号
	static constexpr int32_t BRASS_TUBA=58;//大号
	static constexpr int32_t BRASS_MUTED_TRUMPET=59;//加弱音器小号
	static constexpr int32_t BRASS_FRENCH_HORN=60;//法国号（圆号）
	static constexpr int32_t BRASS_BRASS_SECTION=61;//铜管组（铜管乐器合奏音色）
	static constexpr int32_t BRASS_SYNTH_BRASS_1=62;//合成铜管音色1
	static constexpr int32_t BRASS_SYNTH_BRASS_2=63;//合成铜管音色2
	//		簧管类
	static constexpr int32_t REED_SOPRANO_SAX=64;//高音萨克斯风
	static constexpr int32_t REED_ALTO_SAX=65;//次中音萨克斯风
	static constexpr int32_t REED_TENOR_SAX=66;//中音萨克斯风
	static constexpr int32_t REED_BARITONE_SAX=67;//低音萨克斯风
	static constexpr int32_t REED_OBOE=68;//双簧管
	static constexpr int32_t REED_ENGLISH_HORN=69;//英国管
	static constexpr int32_t REED_BASSOON=70;//巴松（大管）
	static constexpr int32_t REED_CLARINET=71;//单簧管（黑管）
	//笛类
	static constexpr int32_t PIPE_PICCOLO=72;//短笛
	static constexpr int32_t PIPE_FLUTE=73;//长笛
	static constexpr int32_t PIPE_RECORDER=74;//竖笛
	static constexpr int32_t PIPE_PAN_FLUTE=75;//排箫
	static constexpr int32_t PIPE_BOTTLE_BLOW=76;//芦笛
	static constexpr int32_t PIPE_SHAKUHACHI=77;//日本尺八
	static constexpr int32_t PIPE_WHISTLE=78;//口哨声
	static constexpr int32_t PIPE_OCARINA=79;//奥卡雷那
	//合成主音类
	static constexpr int32_t LEAD_SQUARE=80;//(SQUARE)_合成主音1（方波）
	static constexpr int32_t LEAD_SAWTOOTH=81;//(SAWTOOTH)_合成主音2（锯齿波）
	static constexpr int32_t LEAD_CALIOPE_LEAD=82;//(CALIOpe_lead)_合成主音3
	static constexpr int32_t LEAD_CHIFF_LEAD=83;//(CHIFF_Lead)_合成主音4
	static constexpr int32_t LEAD_CHARANG=84;//(CHARANG)_合成主音5
	static constexpr int32_t LEAD_VOICE=85;//(VOICE)_合成主音6（人声）
	static constexpr int32_t LEAD_FIFTHS=86;//(FIFTHS)_合成主音7（平行五度）
	static constexpr int32_t LEAD_BASS_LEAD=87;//(BASS+LEAd)合成主音8（贝司加主音）
	//合成音色类
	static constexpr int32_t PAD_NEW_AGE=88;//(NEW_AGE)_合成音色1（新世纪）
	static constexpr int32_t PAD_WARM=89;//(WARM)_合成音色2_（温暖）
	static constexpr int32_t PAD_POLYSYNTH=90;//(POLYSYNTH)_合成音色3
	static constexpr int32_t PAD_CHOIR=91;//(CHOIR)_合成音色4_（合唱）
	static constexpr int32_t PAD_BOWED=92;//(BOWED)_合成音色5
	static constexpr int32_t PAD_METALLIC=93;//(METALLIC)_合成音色6_（金属声）
	static constexpr int32_t PAD_HALO=94;//(HALO)_合成音色7_（光环）
	static constexpr int32_t PAD_SWEEP=95;//(SWEEP)_合成音色8
	//合成效果类
	static constexpr int32_t FX_RAIN=96;//(RAIN) 合成效果 1 雨声
	static constexpr int32_t FX_SOUNDTRACK=97;//(SOUNDTRACk) 合成效果 2 音轨
	static constexpr int32_t FX_CRYSTAL=98;//(CRYSTAL) 合成效果 3 水晶
	static constexpr int32_t FX_ATMOSPHERE=99;//(ATMOSPHERe) 合成效果 4 大气
	static constexpr int32_t FX_BRIGHTNESS=100;//(BRIGHTNEss) 合成效果 5 明亮
	static constexpr int32_t FX_GOBLINS=101;//(GOBLINS) 合成效果 6 鬼怪
	static constexpr int32_t FX_ECHOES=102;//(ECHOES) 合成效果 7 回声
	static constexpr int32_t FX_SCI_FI=103;//(SCI-FI) 合成效果 8 科幻
	//		民间乐器类
	static constexpr int32_t ETHNIC_SITAR=104;//西塔尔（印度）
	static constexpr int32_t ETHNIC_BANJO=105;//班卓琴（美洲）
	static constexpr int32_t ETHNIC_SHAMISEN=106;//三昧线（日本）
	static constexpr int32_t ETHNIC_KOTO=107;//十三弦筝（日本）
	static constexpr int32_t ETHNIC_KALIMBA=108;//卡林巴
	static constexpr int32_t ETHNIC_BAGPIPE=109;//风笛
	static constexpr int32_t ETHNIC_FIDDLE=110;//民族提琴
	static constexpr int32_t ETHNIC_SHANAI=111;//山奈
	//打击乐器类
	static constexpr int32_t PERCUSSIVE_TINKLE_BELL=112;//叮当铃
	static constexpr int32_t PERCUSSIVE_AGOGO=113;//AGOGO
	static constexpr int32_t PERCUSSIVE_STEEL_DRUMS=114;//钢鼓
	static constexpr int32_t PERCUSSIVE_WOODBLOCK=115;//木鱼
	static constexpr int32_t PERCUSSIVE_TAIKO_DRUM=116;//太鼓
	static constexpr int32_t PERCUSSIVE_MELODIC_TOM=117;//通通鼓
	static constexpr int32_t PERCUSSIVE_SYNTH_DRUM=118;//合成鼓
	static constexpr int32_t PERCUSSIVE_REVERSE_CYMBAL=119;//铜钹
	//		声音效果类
	static constexpr int32_t EFFECTS_GUITAR_FRET_NOISE=120;//吉他换把杂音
	static constexpr int32_t EFFECTS_BREATH_NOISE=121;//呼吸声
	static constexpr int32_t EFFECTS_SEASHORE=122;//海浪声
	static constexpr int32_t EFFECTS_BIRD_TWEET=123;//鸟鸣
	static constexpr int32_t EFFECTS_TELEPHONE_RING=124;//电话铃
	static constexpr int32_t EFFECTS_HELICOPTER=125;//直升机
	static constexpr int32_t EFFECTS_APPLAUSE=126;//鼓掌声
	static constexpr int32_t EFFECTS_GUNSHOT=127;//枪声
	};
	EBCLASS(DrumSet){
	public:
	static constexpr int32_t HIGH_Q=27; // 高频噪声（效果音）
	static constexpr int32_t SLAP=28; // 拍手声（效果音）
	static constexpr int32_t SCRATCH_PUSH=29; // 刮擦声（推）
	static constexpr int32_t SCRATCH_PULL=30; // 刮擦声（拉）
	static constexpr int32_t STICKS=31; // 鼓棒敲击声
	static constexpr int32_t SQUARE_CLICK=32; // 方波滴答声
	static constexpr int32_t METRONOME_CLICK=33; // 节拍器滴答声
	static constexpr int32_t METRONOME_BELL=34; // 节拍器铃声
	static constexpr int32_t BASS_DRUM_ACOUSTIC=35; // 原声底鼓
	static constexpr int32_t BASS_DRUM_1=36; // 电底鼓1
	static constexpr int32_t SIDE_STICK=37; // 边击（鼓边敲击）
	static constexpr int32_t SNARE_ACOUSTIC=38; // 原声军鼓
	static constexpr int32_t HAND_CLAP=39; // 拍手声
	static constexpr int32_t SNARE_ELECTRIC=40; // 电军鼓
	static constexpr int32_t TOM_LOW_FLOOR=41; // 低音地嗵鼓
	static constexpr int32_t HI_HAT_CLOSED=42; // 闭合踩镲
	static constexpr int32_t TOM_HIGH_FLOOR=43; // 高音地嗵鼓
	static constexpr int32_t HI_HAT_PEDAL=44; // 踩镲踏板声
	static constexpr int32_t TOM_LOW=45; // 低音嗵鼓
	static constexpr int32_t HI_HAT_OPEN=46; // 开放踩镲
	static constexpr int32_t TOM_LOW_MID=47; // 中低音嗵鼓
	static constexpr int32_t TOM_HIGH_MID=48; // 中高音嗵鼓
	static constexpr int32_t CYMBAL_CRASH_1=49; // 碎音镲1
	static constexpr int32_t TOM_HIGH=50; // 高音嗵鼓
	static constexpr int32_t CYMBAL_RIDE_1=51; // 节奏镲1
	static constexpr int32_t CYMBAL_CHINESE=52; // 中国镲
	static constexpr int32_t BELL_RIDE=53; // 钟声节奏镲
	static constexpr int32_t TAMBOURINE=54; // 铃鼓
	static constexpr int32_t CYMBAL_SPLASH=55; // 溅水镲
	static constexpr int32_t COWBELL=56; // 牛铃
	static constexpr int32_t CYMBAL_CRASH_2=57; // 碎音镲2
	static constexpr int32_t VIBRA_SLAP=58; // 振动拍板
	static constexpr int32_t CYMBAL_RIDE_2=59; // 节奏镲2
	static constexpr int32_t BONGO_HI=60; // 高音邦戈鼓
	static constexpr int32_t BONGO_LOW=61; // 低音邦戈鼓
	static constexpr int32_t CONGA_MUTE=62; // 闷音康加鼓
	static constexpr int32_t CONGA_HI=63; // 高音康加鼓
	static constexpr int32_t CONGA_LOW=64; // 低音康加鼓
	static constexpr int32_t TIMBALE_HI=65; // 高音天巴雷鼓
	static constexpr int32_t TIMBALE_LOW=66; // 低音天巴雷鼓
	static constexpr int32_t AGOGO_HI=67; // 高音阿哥哥铃
	static constexpr int32_t AGOGO_LOW=68; // 低音阿哥哥铃
	static constexpr int32_t CABASA=69; // 卡巴萨（砂槌）
	static constexpr int32_t MARACAS=70; // 沙球
	static constexpr int32_t WHISTLE_HIGH=71; // 高音口哨
	static constexpr int32_t WHISTLE_LOW=72; // 低音口哨
	static constexpr int32_t GUIRO_SHORT=73; // 短刮瓜
	static constexpr int32_t GUIRO_LONG=74; // 长刮瓜
	static constexpr int32_t CLAVES=75; // 克拉维棍（响棒）
	static constexpr int32_t WOOD_BLOCK_HIGH=76; // 高音木鱼
	static constexpr int32_t WOOD_BLOCK_LOW=77; // 低音木鱼
	static constexpr int32_t CUICA_HIGH=78; // 高音奎卡鼓
	static constexpr int32_t CUICA_LOW=79; // 低音奎卡鼓
	static constexpr int32_t TRIANGLE_MUTE=80; // 闷音三角铁
	static constexpr int32_t TRIANGLE_OPEN=81; // 开放三角铁
	static constexpr int32_t SHAKER=82; // 沙锤
	static constexpr int32_t JINGLE_BELL=83; // 铃铛
	static constexpr int32_t BELL_TREE=84; // 铃树
	static constexpr int32_t CASTANETS=85; // 响板
	static constexpr int32_t SURDO_MUTE=86; // 闷音苏度鼓
	static constexpr int32_t SURDO_OPEN=87; // 开放苏度鼓
	//
	};
	EBCLASS(MIDIEvent){
	public:
	EventType type=FF;
	int32_t deltaTimeTicks=0;
	MIDIEvent(int32_t deltaTimeTicks) : deltaTimeTicks(deltaTimeTicks){}
	virtual EventType getType()=0;
	virtual ~MIDIEvent()=default;
	};
	EBCLASS(Track){
	public:
	yzrilyzr_collection::ArrayList<MIDIEvent *> events;
	yzrilyzr_lang::String  name;
	yzrilyzr_lang::String toString() const override{
		return "Track:" + name;
	}
	};
	EBCLASS(MIDISequence){
	public:
	int16_t midiFormat=0;
	int16_t midiTrackCount=0;
	int16_t ticksForQuarterNote=0;
	int32_t framePerSecond=0;
	int32_t ticksPerFrame=0;
	yzrilyzr_collection::ArrayList<Track *> tracks;
	};
	static MIDISequence * parse(yzrilyzr_io::InputStream & is);
	static void parseTrack(Track * track, const yzrilyzr_array::ByteArray& midiTrack);
	ECLASS(SysexMessage, public MIDIEvent){
	public:
	yzrilyzr_array::ByteArray * b=nullptr;
	SysexMessage(int32_t deltaTimeTicks) : MIDIEvent(deltaTimeTicks), b(nullptr){}
	~SysexMessage(){
		delete b;
	}
	EventType getType()override{
		return EventType::Sysex;
	}
	};
	ECLASS(FFMessage, public MIDIEvent){
	public:
	int32_t type=0;
	yzrilyzr_array::ByteArray * b=nullptr;
	yzrilyzr_lang::String  text;
	int32_t quarterNoteDurationMicroSeconds=0;
	int8_t beatNumerator=0;
	int32_t beatDenominator=0;
	int8_t ticksPerMidiClk=0;
	int8_t ticks24MidiClk=0;
	FFMessage(int32_t deltaTimeTicks) : MIDIEvent(deltaTimeTicks){}
	~FFMessage(){
		delete b;
	}
	EventType getType()override{
		return EventType::FF;
	}
	yzrilyzr_lang::String toString() const override{
		return yzrilyzr_lang::StringFormat::format("[FF:%d %s]", type, b);
	}
	};
	ECLASS(MIDIChannelEvent, public MIDIEvent){
	public:
	int32_t channel;
	int32_t type;
	MIDIChannelEvent(int32_t deltaTimeTicks, int32_t type) : MIDIEvent(deltaTimeTicks), type(type), channel(type & 0b1111){}
	virtual MIDIChannelEvent * newInstance(int32_t deltaTimeTicks, int32_t par1, yzrilyzr_io::DataInputStream & ids2)=0;
	};
	ECLASS(MIDINote, public MIDIChannelEvent){
		/**
		 * 0:NoteOff, 1:NoteOn, 2:NoteAfterTouch
		 */
	public:
	int32_t action;
	int32_t id;
	int32_t velocity;
	MIDINote(int32_t deltaTimeTicks, int32_t type, int32_t id, int32_t velocity) : MIDIChannelEvent(deltaTimeTicks, type),
		id(id),
		velocity(velocity),
		action(((0x80 <= type && type <= 0x8f) || velocity == 0)?0:((0x90 <= type && type <= 0x9f)?1:((0xa0 <= type && type <= 0xaf)
																									  ?2
																									  :throw std::runtime_error(
																										  "invalid")))){}
	virtual MIDIChannelEvent * newInstance(int32_t deltaTimeTicks, int32_t par1, yzrilyzr_io::DataInputStream & ids2) override{
		return new MIDINote(deltaTimeTicks, type, par1, ids2.read());
	}

	EventType getType()override{
		return EventType::Note;
	}
	yzrilyzr_lang::String toString() const override{
		return yzrilyzr_lang::StringFormat::format("[Note:%d Ch:%d ID:%d Vel:%d Tick:%d]", action, channel, id, velocity, deltaTimeTicks);
	}
	};
	ECLASS(MIDIChannelControl, public MIDIChannelEvent){
	public:
	int32_t control;
	int32_t value;
	MIDIChannelControl(int32_t deltaTimeTicks, int32_t type, int32_t control, int32_t value) : MIDIChannelEvent(deltaTimeTicks, type){
		this->control=control;
		this->value=value;
	}
	virtual MIDIChannelEvent * newInstance(int32_t deltaTimeTicks, int32_t par1, yzrilyzr_io::DataInputStream & ids2) override{
		return new MIDIChannelControl(deltaTimeTicks, type, par1, ids2.read());
	}

	EventType getType()override{
		return EventType::ChannelControl;
	}
	yzrilyzr_lang::String toString() const override{
		return yzrilyzr_lang::StringFormat::format("[CC:%d Ch:%d Val:%d]", control, channel, value);
	}
	};
	ECLASS(MIDIProgramChange, public MIDIChannelEvent){
	public:
	int32_t num;
	MIDIProgramChange(int32_t deltaTimeTicks, int32_t type, int32_t num) : MIDIChannelEvent(deltaTimeTicks, type){
		this->num=num;
	}
	virtual MIDIChannelEvent * newInstance(int32_t deltaTimeTicks, int32_t par1, yzrilyzr_io::DataInputStream & ids2) override{
		return new MIDIProgramChange(deltaTimeTicks, type, par1);
	}

	EventType getType()override{
		return EventType::ProgramChange;
	}
	yzrilyzr_lang::String toString() const override{
		return yzrilyzr_lang::StringFormat::format("[PC:%d Ch:%d]", num, channel);
	}
	};
	ECLASS(MIDIChannelPressure, public MIDIChannelEvent){
	public:
	int32_t value;
	MIDIChannelPressure(int32_t deltaTimeTicks, int32_t type, int32_t value) : MIDIChannelEvent(deltaTimeTicks, type){
		this->value=value;
	}
	virtual MIDIChannelEvent * newInstance(int32_t deltaTimeTicks, int32_t par1, yzrilyzr_io::DataInputStream & ids2) override{
		return new MIDIChannelPressure(deltaTimeTicks, type, par1);
	}

	EventType getType()override{
		return EventType::ChannelPressure;
	}
	yzrilyzr_lang::String toString() const override{
		return yzrilyzr_lang::StringFormat::format("[Pressure:%d Ch:%d]", value, channel);
	}
	};
	ECLASS(MIDIPitchBend, public MIDIChannelEvent){
	public:
	int32_t value;
	MIDIPitchBend(int32_t deltaTimeTicks, int32_t type, int32_t vl, int32_t vh) : MIDIChannelEvent(deltaTimeTicks, type){
		this->value=(vl & 0x7f) | ((vh & 0x7f) << 7);
	}
	virtual MIDIChannelEvent * newInstance(int32_t deltaTimeTicks, int32_t par1, yzrilyzr_io::DataInputStream & ids2) override{
		return new MIDIPitchBend(deltaTimeTicks, type, par1, ids2.read());
	}

	EventType getType()override{
		return EventType::ChannelPitchBend;
	}
	yzrilyzr_lang::String toString() const override{
		return yzrilyzr_lang::StringFormat::format("[Pitch:%d Ch:%d]", value, channel);
	}
	};
	};
}